package com.point;

import org.gavaghan.geodesy.Ellipsoid;
import org.gavaghan.geodesy.GeodeticCalculator;
import org.gavaghan.geodesy.GeodeticCurve;
import org.gavaghan.geodesy.GlobalCoordinates;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;

/**
 * Point util
 *
 * @description:
 * @author: cyj
 * @date 2022 -07-27 18:07:47
 */
public class PointUtil {

    /**
     * 默认地球半径
     */
    private static double EARTH_RADIUS = 6371000;//赤道半径(单位m)

    /**
     * Is pt in poly boolean 当前经纬度是不是在多边形范围圈内
     * 根据射线法
     * 射线法的思想是：以目标点为端点引一条射线，计算这条射线和多边形所有边的交点数目。如果交点个数为奇数，则点在多边形部内部，反之则在多边形外部。
     *
     * @param nowPoint 当前坐标
     * @param ps       多边形各个顶点，至少3个点, 图形连线顶点顺序是按照这个数组顺序！！！！，数组尾部和头部坐标相连
     * @return the boolean
     */
    public static boolean isPtInPoly(Point nowPoint, Point[] ps) {
        int iSum, iCount, iIndex;
        double dLon1 = 0, dLon2 = 0, dLat1 = 0, dLat2 = 0, dLon;
        if (ps.length < 3) {
            return false;
        }
        iSum = 0;
        iCount = ps.length;
        for (iIndex = 0; iIndex < iCount; iIndex++) {
            if (iIndex == iCount - 1) {
                dLon1 = ps[iIndex].getLon();
                dLat1 = ps[iIndex].getLat();
                dLon2 = ps[0].getLon();
                dLat2 = ps[0].getLat();
            } else {
                dLon1 = ps[iIndex].getLon();
                dLat1 = ps[iIndex].getLat();
                dLon2 = ps[iIndex + 1].getLon();
                dLat2 = ps[iIndex + 1].getLat();
            }
            // 以下语句判断A点是否在边的两端点的水平平行线之间，在则可能有交点，开始判断交点是否在左射线上
            if (((nowPoint.getLat() >= dLat1) && (nowPoint.getLat() < dLat2)) || ((nowPoint.getLat() >= dLat2) && (nowPoint.getLat() < dLat1))) {
                if (Math.abs(dLat1 - dLat2) > 0) {
                    //得到 A点向左射线与边的交点的x坐标：
                    dLon = dLon1 - ((dLon1 - dLon2) * (dLat1 - nowPoint.getLat())) / (dLat1 - dLat2);
                    // 如果交点在A点左侧（说明是做射线与 边的交点），则射线与边的全部交点数加一：
                    if (dLon < nowPoint.getLon()) {
                        iSum++;
                    }
                }
            }
        }
        if ((iSum % 2) != 0) {
            return true;
        }
        return false;
    }

    /**
     * Gets distance meter 计算经纬度之间的距离，返回单位M
     *
     * @param gpsFrom   gps from
     * @param gpsTo     gps to
     * @param ellipsoid ellipsoid
     * @return the distance meter
     */
    public static double getDistanceMeter(GlobalCoordinates gpsFrom, GlobalCoordinates gpsTo, Ellipsoid ellipsoid) {
        //创建GeodeticCalculator，调用计算方法，传入坐标系、经纬度用于计算距离
        GeodeticCurve geoCurve = new GeodeticCalculator().calculateGeodeticCurve(ellipsoid, gpsFrom, gpsTo);
        return geoCurve.getEllipsoidalDistance();
    }

    /**
     * 转化为弧度(rad)
     * */
    private static double rad(double d)
    {
        return d * Math.PI / 180.0;
    }

    /**
     * 计算经纬度之间的距离，返回单位M
     * @return 返回的距离，单位m
     * */
    public static double getDistance(Point source, Point target) {
        double radLat1 = rad(source.getLat());
        double radLat2 = rad(target.getLat());
        double a = radLat1 - radLat2;
        double b = rad(source.getLon()) - rad(target.getLon());
        double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2)));
        s = s * EARTH_RADIUS;
        s = Math.round(s * 10000) / 10000;
        return s;
    }

    public static void main(String[] args) throws UnsupportedEncodingException {



    }
}
